#include <iostream>
#include "Common.hpp"
#include "ThreadCache.hpp"
#include "CentralCache.hpp"

void* ThreadCache::Allocate(size_t size)
{
    assert(size < Max_Byte);
    //获取对应的哈希桶下标以及所需要的空间
    //1 先得到对齐之后的字节数是多少 以及映射到那个哈希桶里
    size_t alignSize = SizeClass::RoundUP(size);
    size_t index = SizeClass::Index(size);

    if(!_freelist[index].Empty())
    {
        //直接从tc中拿出一块空间来用就行了
        return _freelist[index].pop();
    }else{
        //从CC中去获取内存空间
        return FetchFromCentralCache(index,alignSize);
    }

}

void ListTooLong(Freelist& freelist,size_t size)
{
    void* start = nullptr;
    void* end = nullptr;
    freelist.PopRange(start,end,freelist.getMaxSize());
    //归还给cc
    CentralCache::create()->ReleaselisttoSpan(start,size);
}
void ThreadCache::Deallocate(void* obj,size_t size)
{
    assert(obj);
    assert(size < Max_Byte);
    size_t index = SizeClass::Index(size);
    _freelist[index].push(obj);
    if(_freelist[index].GetSize() > _freelist[index].getMaxSize())
    {
        ListTooLong(_freelist[index],size);
    }
}

void* ThreadCache::FetchFromCentralCache(size_t index,size_t alignSize)
{
    //通过对齐的字节数，我们需要提供多少块内存给对方
    size_t batchNum = std::min(_freelist[index].getMaxSize(),SizeClass::GetNum(alignSize));
    //看CC中有多少块符合的，有多少返回多少
    if(batchNum == _freelist[index].getMaxSize())
    {
        _freelist[index].getMaxSize()++;//在没有达到极限的情况下，下一次可以多提供一块
    }
    void* start = nullptr;
    void* end = nullptr;
    //从CC中申请内存
    size_t actualNum = CentralCache::create()->FetchRangeObj(start,end,batchNum,alignSize);

    if(actualNum==1)
    {
        assert(start==end);
        return start;
    }else{
        //把多余的内存块挂在tc中
        _freelist[index].pushRange(ObjNext(start),end,actualNum-1);
        //把这段空间直接返回
        return start;
    }
    return start;
}